/**
 * Flaming UI framework
 * @returns
 */
function Flamingo() {
	/**
	 * the list of registered controllers.
	 */
	var _controllers = [],
	/**
	 * the active view
	 */
	_active = null,
	/**
	 * The error view
	 */
	_error = null;

	methods = {
		/**
		 * Concatenate the arguments using provided separator.
		 * @param s the separator.
		 * @returns String the concatenation result.
		 */
		concat: function(s) { return Array.prototype.slice.call(arguments, 1).join(s); },
		/**
		 * Execute an AJAX request using jQuery.ajax.
		 * @param u the URL to invoke
		 * @param t the request type (i.e. GET, POST ...)
		 * @param d the data to pass as a query string
		 * @param c flag toggle cache usage
		 * @param a flag asynchronous true or synchronous false request.
		 * @param obj the object that contains the callback
		 * @param scb success callback function
		 * @param ecb error callback function
		 */
		ajax: function(u,t,d,c,a,obj,scb,ecb) {
			$.ajax({ url: u, type: t, data: d, cache: (this.valid(c) ? c : false), async: a, success: function(){scb.apply(obj,arguments);}, error: function(){ecb.apply(obj,arguments);} });
		},
		/**
		 * Checks if the given object is valid or not.
		 * @param o the object to check
		 * @returns true if the object is valid false otherwise.
		 */
		valid: function(o) {return null!=o && undefined!=o;},
		/**
		 * Check if the given objects ore same.
		 * @param o1 the first object
		 * @param o2 the second object
		 * @returns true if the the two objects ore same.
		 */
		equals: function(o1,o2) {return o1===o2;},
		/**
		 * Replaces all the place-holder (in order they appear) using the given values.
		 * @param p the place-holder
		 * @param vs the list of values
		 * @param s the source string
		 * @returns the replaced string 
		 */
		replace: function(p,vs,s) { var t = s; for(var k in vs) { var v = vs[k]; t = t.replace(p,v); } return t; },
		/**
		 * Round the given number to the requested number of decimals.
		 * @param n the number to round.
		 * @param d the number of decimal to round to.
		 * @returns the reounded number.
		 */
		round: function(n,d) {var m=Math.pow(10,d); return Math.round(n*m)/m;},
		/**
		 * Register a new controller
		 * @param n the controller name
		 * @param c the controller object
		 */
		addController: function(n,c) {_controllers[n]=c;},
		setErrorView: function(e) {this._error=e;},
		/**
		 * Invoke the requested controller and updates the view.
		 * @param c the controller to invoke.
		 */
		invoke: function(c) {
			/*
			 * Correct sequence of events should be:
			 * 1) hide current view
			 * 2) show loading popup
			 * 3) call execute on controller
			 * 4) collect view from controller
			 * 5) hide loading popup
			 * 6) show new view 
			 */
			var controller = _controllers[c];
			if(this.valid(controller)) {
				if(this.valid(_active)) { _active.hide(); }
				view( controller.execute() );
				_active.show(); _active.afterShow();
			} else {
				throw new TypeError(this.concat(" ", "Invalid controler name:", c));
			}
		},
	};
	function view(v) { _active = (null!=v && undefined!=v)  ? v : (null!=_active && undefined!=_active) ? _active : _error; };
	
	for(var k in methods) { Flamingo.prototype[k] = methods[k]; }
	/**
	 * Fixes the construction status
	 */
	return true;
}
// define flamingo shortcut
window.F = window.flamingo = new Flamingo();

function Class() {}
Class.extend = function(o) {
	function N() {}
	for(var k in this) { N.prototype[k] = this[k]; }
	for(var k in o) { N.prototype[k] = o[k]; }
	var ret = new N();
	ret.constructor = N;
	ret.init();
	return ret;
}
Class.clone = function(obj) {
	function Clone() { } 
    Clone.prototype = obj;
    var c = new Clone();
    c.constructor = Clone;
    return c;
}

/**
 * Defines a controller, the controller is responsible to mediate between the model and view after an update 
 * request comes from the current active view. 
 */
var Controller = Class.extend({
	/**
	 * initialise the class
	 */
	init: function() {},
	/**
	 * Execute the business logic
	 */
	execute: function() {}
});
/**
 * Defines a View abstract class, the view abstract the end user UI.
 */
var View = Class.extend({
	/**
	 * initialise the class
	 * @param o an object that contains initialisation parameters.
	 */
	init: function(o){},
	/**
	 * Show the current view, for more flexibility the implementation is left to the implementor.
	 */
	show: function() {},
	/**
	 * This function is called after the show method, it is useful when a the view is rendering an area 
	 * but the main view (or one of its parent) display properties is set to none getting the size of the 
	 * view equal to zero. 
	 */
	afterShow: function() {},
	/**
	 * Hide the current view, to achieve more flexibility in data presentation logic the implementation 
	 * is left to the implementor. 
	 */
	hide: function() {},
	/**
	 * Render the current view, this method is supposed to be invoked by the controller, so the data 
	 * are ready to be shown to the end user. 
	 */
	render: function(o) {}
});
/**
 * Defines a Service class, the service class identifies the link between a controller and DAO logic.
 */
var Service = Class.extend({
	/**
	 * initialise the class
	 */
	init: function(){}
});


F.setErrorView(View.extend({
	show: function(o) {
		alert("Generic error unable to show main UI");
	}
}));

